import java.util.PriorityQueue;
import java.util.stream.StreamSupport;

/**
 * 用来存放执行的时间和任务
 */
class MYTIMETASK implements  Comparable<MYTIMETASK>{
    private Runnable runnable;//此处为执行的任务代码
    private long time;//此处为执行任务的时间,此处的时间是一个相对时间,此处的时间是一个ms级别的时间戳
    //构造方法
    //获取时间的方法
    public long getTime(){
        return  this.time;
    }
    //提供任务执行的接口
    public void run(){
        this.runnable.run();
    }
    public MYTIMETASK(Runnable runnable,long delay){
        this.runnable=runnable;
        this.time=System.currentTimeMillis()+delay;
    }

    @Override
    public int compareTo(MYTIMETASK o) {
        return (int)(this.time-o.time);//这里是long类型,要进行强制类型转换
    }
}

/**
 * 计时器,用来判断当前哪一个任务该执行了
 */
class MYTIMER{
    private Thread t=null;//定义一个线程来不断地进行扫描,看是否有任务到时间了,不断地去扫描
    private PriorityQueue<MYTIMETASK>queue=new PriorityQueue<>();//此处定义一个优先级队列来存放任务,
    //但是这里需要注意,我们的优先级队列在进行存储自定义数据时,需要实现Comparable接口方法.,因此上述代码应做出改动
    private Object locker1=new Object();
    public void schedule(Runnable runnable,long delay){//使用schedule进行任务的添加
        synchronized (locker1) {
            MYTIMETASK task = new MYTIMETASK(runnable, delay);
            queue.offer(task);//进行任务的添加
            locker1.notify();
        }
    }

    //提供一个cancel方法来进行计时器任务的结束
    public void cancel(){
        t.interrupt();
    }
    //在构造方法里面创建一个线程来进行扫描,严阵以待
    public MYTIMER(){
        t=new Thread(()->{
            while(!Thread.currentThread().isInterrupted()){
                try {
                    synchronized (locker1) {
                        while (queue.isEmpty()) {
                            locker1.wait();
                            //continue;//如果队列为空,则不能进行peek,要循环到有任务进来了,才可以执行当前逻辑
                        }
                        //如果不为空,我们则需要查看队列顶部的任务是否到了执行的时间
                        MYTIMETASK task = queue.peek();
                        if (System.currentTimeMillis() >= task.getTime()) {
                            task.run();//到了执行任务的时间,则需要进行执行
                            queue.poll();//执行了则需要进行出队列操作
                        }
                        else{
                            locker1.wait(task.getTime()-System.currentTimeMillis());

                        }
                    }
                }
                catch (InterruptedException e){
                        break;
                }

            }
        });
        t.start();//开启这个线程
    }

}
public class TimeCounter {

    public static void main(String[] args) throws InterruptedException {
  MYTIMER timer=new MYTIMER();
  timer.schedule(new Runnable() {
      @Override
      public void run() {
          System.out.println("hello 3000");
      }
  },3000);
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 2000");
            }
        },2000);
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 1000");
            }
        },1000);
        Thread.sleep(5000);
        timer.cancel();
    }
}
